<?php

namespace Hx\Mvc\Model;

use Hx\Db\Sql;
use Hx\Di;

/**
 * 模型类基类
 * @property \Hx\Db\Base|\Hx\Db\PDO db
 */
abstract class Table extends Di {

    /**
     * 操作表名称
     * @var string
     */
    protected $table;

    /**
     * 设置数据库
     * @param string $name
     * @return $this
     */
    protected function setDb($name = 'Hx\Db\PDO:database') {
        $name = isset($this->dbName) ? $this->dbName : $name;
        return $this->set('db', $name, TRUE);
    }

    /**
     * 魔术方法获取对象
     * @param string $name
     * @return \Hx\Db\Base|null
     */
    public function __get($name) {
        if ($name === 'db') {
            return $this->setDb();
        }
        return NULL;
    }

    /**
     * 设置表
     * @param string $table
     * @return $this
     */
    protected function setTable($table) {
        $this->table = $table;
        return $this;
    }

    //-------------------------

    /**
     * 调用SQL类
     * @param array $column
     * @param string $table
     * @return Sql
     */
    protected function useSql($column = array('*'), $table = NULL) {
        if (is_string($column)) {
            $column = explode(',', $column);
        }
        return new Sql($table === NULL ? $this->table : $table, $column);
    }

    //-------------------------

    /**
     * 处理SQL类附加设置
     * @param Sql $sql
     * @param array $option
     * @return Sql
     */
    private function _parseSqlOption(Sql $sql, array $option) {
        if ($option['where']) {
            $sql->where($option['where']);
        }
        if ($option['order']) {
            $sql->order($option['order']);
        }
        if ($option['limit']) {
            $limit = explode(',', $option['limit']);
            $sql->limit($limit[0], $limit[1]);
        }
        if ($option['page']) {
            $paged = explode(',', $option['page']);
            $sql->page($paged[0], $paged[1]);
        }
        return $sql;
    }

    //---------------------------

    /**
     * INSERT数据
     * @param array $data
     * @param array $option
     * @return array
     */
    public function insert($data, array $option = array()) {
        $columns = array_keys($data);
        $sql = $this->_parseSqlOption($this->useSql($columns), $option);
        if (is_array($option['param'])) {
            $data += $option['param'];
        }
        $this->db->exec($sql->insert(), $data);
        $data['id'] = $this->db->lastId();
        return $data;
    }

    /**
     * UPDATE数据
     * @param array $data
     * @param array $option
     * @return bool
     */
    public function update($data, array $option = array()) {
        $columns = array_keys($data);
        $sql = $this->_parseSqlOption($this->useSql($columns), $option);
        if (is_array($option['param'])) {
            $data += $option['param'];
        }
        $this->db->exec($sql->update(), $data);
        return TRUE;
    }

    /**
     * DELETE数据
     * @param array $option
     * @return bool
     */
    public function delete(array $option) {
        $sql = $this->useSql();
        $sql = $this->_parseSqlOption($sql, $option);
        if (!$option['param']) {
            $option['param'] = array();
        }
        $this->db->exec($sql->delete(), $option['param']);
        return TRUE;
    }

    /**
     * 查询一个数据
     * @param array $option
     * @param array|string $columns
     * @return mixed
     */
    public function only(array $option, $columns = array('*')) {
        $sql = $this->useSql($columns);
        $sql = $this->_parseSqlOption($sql, $option);
        if (!$option['param']) {
            $option['param'] = array();
        }
        return $this->db->exec($sql->select(), $option['param'])->fetch();
    }

    /**
     * 查询一组数据
     * @param array $option
     * @param array|string $columns
     * @return array
     */
    public function select(array $option, $columns = array('*')) {
        $sql = $this->useSql($columns);
        $sql = $this->_parseSqlOption($sql, $option);
        if (!$option['param']) {
            $option['param'] = array();
        }
        return $this->db->exec($sql->select(), $option['param'])->fetch(TRUE);
    }

    /**
     * 统计数组调价
     * @param array $option
     * @return int
     */
    public function count(array $option) {
        $sql = $this->useSql('count(*) AS num');
        if ($option['where']) {
            $sql->where($option['where']);
        }
        if ($option['order']) {
            $sql->order($option['order']);
        }
        if (!$option['param']) {
            $option['param'] = array();
        }
        return $this->db->exec($sql->select(), $option['param'])->fetch()->num;
    }

}